#pragma once
#include "thread.hpp"
#include "lockGuard.hpp"
#include <iostream>
#include <unistd.h>
#include <queue>
#include"log.hpp"

const int g_thread_num = 3;

template <class T>
class ThreadPool
{
public:
    pthread_mutex_t *getMutex()
    {
        return &lock;
    }
    bool isEmpty()
    {
        return _taskQueue.empty();
    }
    void waitCond()
    {
        pthread_cond_wait(&cond, &lock);
    }
    T getTask()
    {
        T t = _taskQueue.front();
        _taskQueue.pop();
        return t;
    }

public:
    ThreadPool(int thread_num = g_thread_num) : _num(thread_num)
    {
        pthread_mutex_init(&lock, nullptr);
        pthread_cond_init(&cond, nullptr);
        for (int i = 0; i < _num; i++)
        {
            _threads.push_back(new Thread(i, routine, this));
        }
    }
    void run()
    {
        for (auto &iter : _threads)
        {
            iter->start();
            // std::cout << iter->name() << "启动成功" << std::endl;
            logMessage(NORMAL,"%s %s\n",iter->name().c_str(),"启动成功");
        }
    }
    static void* routine(void *args)
    {
        ThreadData *td = (ThreadData *)args;
        ThreadPool *tp = (ThreadPool *)td->_args;

        while (true)
        {
            T task;
            {
                // 加锁
                lockGuard lockGuard(tp->getMutex());
                // 等待
                while (tp->_taskQueue.empty())
                {
                    tp->waitCond();
                }
                // 读取任务,任务是共享的，将任务从共享空间拿到我们的私有空间
                task = tp->getTask();
                sleep(1);
            }
            task(td->_name);
        }
        return nullptr;
    }
    // 要对任务队列做加锁
    void pushTask(const T &task)
    {
        lockGuard lockGuard(&lock);
        _taskQueue.push(task);
        // 有任务加唤醒线程
        pthread_cond_signal(&cond);
    }
    // for test
    void joins()
    {

        for (auto &iter : _threads)
        {
            iter->join();
        }
    }
    ~ThreadPool()
    {
        for (auto &iter : _threads)
        {
            // iter->join();
            delete iter;
        }
        pthread_mutex_destroy(&lock);
        pthread_cond_destroy(&cond);
    }

private:
    std::vector<Thread*> _threads;
    int _num;
    std::queue<T> _taskQueue;
    //方案2：
    //queue1,queue2
    //std::queue<T> *p_queue,*c_queue
    //p_queue->queue1,c_queue->queue2
    //p_queue->生产一批任务，swap(p_queue,c_queue),
    //然后c_queue消费，消费完之后再交换
    //交换的时候要加锁，指针操作可以符合一定的策略，来满足消费和生产策略，同时还可以搞一个线程专门检测
    //queue1是否为满，queue2是否为空,之后执行交换
    pthread_mutex_t lock;
    pthread_cond_t cond;
};